package com.java.jvm.loader;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 自定义类加载器
 * 打破双亲委派机制？
 * 1)为什么要打破？(一个tomcat中假如运行两个服务，
 *                这两个服务中有类全名相同的类如何加载？)
 * 2)如何打破？(重写ClassLoader类中的loadClass方法)
 */
public class BreakDoubleParentAppClassLoader extends ClassLoader{

    private String baseDir;
    public BreakDoubleParentAppClassLoader(String baseDir){
        this.baseDir=baseDir;
    }

    //一般要打破双亲委派机制时可以重写loadClass方法
    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        try {
            //自己直接从指定位置加载自己写的类
            Class<?> clazz = findClass(name);
            return clazz;
        }catch (Exception e){
            return super.loadClass(name, resolve);//使用双亲委派机制加载(推荐基础类库还要使用这种方式)
        }
    }

    @Override
    protected Class<?> findClass(String className) throws ClassNotFoundException {
        String classPath=baseDir+className.replace(".", "\\")+".class";
        File file=new File(classPath);
        InputStream in=null;
        try {
            in=new FileInputStream(file);
            byte[] array=new byte[in.available()];//in.available()获取流中有效字节数
            int len=in.read(array);
            return defineClass(className, array, 0, len);
        }catch (IOException e){
            throw new RuntimeException(e);
        }finally{
            if(in!=null)try{in.close();}catch (Exception e){}
        }
    }

    public static void main(String[] args) throws ClassNotFoundException {
        BreakDoubleParentAppClassLoader loader1=
                new BreakDoubleParentAppClassLoader("E:\\TCGBIV\\DEVCODES\\jht\\");
        BreakDoubleParentAppClassLoader loader2=
                new BreakDoubleParentAppClassLoader("E:\\TCGBIV\\DEVCODES\\jht\\");
        //loader.loadClass("pkg.Hello");
        Class<?> c1=Class.forName("pkg.Hello",true,loader1);
        Class<?> c2=Class.forName("pkg.Hello",true,loader2);
        System.out.println(c1==c2);//false
    }
    //思考？
    //1)一个类的字节码对象在内存中只能有一份，正确吗？不正确
    //2)判断两个类的字节码对象是否相同标准是什么？（类相同，类的加载器也要相同）
    //3)每个类加载器都有自己的内存，正确吗？正确。



}
